home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Games / Chess / Source / Board3D.m < prev    next >
Text File  |  1994-04-01  |  16KB  |  658 lines

  1. #import <c.h>
  2.  
  3. #include <sys/types.h>
  4. #include <sys/time.h>
  5. #import <appkit/appkit.h>
  6.  
  7. #import "chess_strings.h"
  8. #import "Chess.h"
  9. #import "gnuchess.h"
  10. #import "Board3D.h"
  11. #import "Square3D.h"
  12.  
  13. #define PIECE_WIDTH_3D 55
  14. #define BACK_STORE_WIDTH 80
  15. #define PIECE_HEIGHT_3D 95
  16. #define BACK_STORE_HEIGHT 110
  17.  
  18. extern PSWtrapezoid ();
  19.  
  20. /*  Each set of points describes the vertical lines along the board. */
  21. struct NXLine {
  22.   NXPoint a,b;
  23. };
  24.  
  25. #define BASE_X 89
  26. struct NXLine vertical[] = {
  27.   {{BASE_X,122},{BASE_X+61,467}},
  28.   {{BASE_X+71,122},{BASE_X+111,467}},
  29.   {{BASE_X+135,122},{BASE_X+162,467}},
  30.   {{BASE_X+200,122},{BASE_X+212,467}},
  31.   {{BASE_X+265,122},{BASE_X+265,467}},
  32.   {{BASE_X+330,122},{BASE_X+316,467}},
  33.   {{BASE_X+393,122},{BASE_X+367,467}},
  34.   {{BASE_X+459,122},{BASE_X+419,467}},
  35.   {{BASE_X+524,122},{BASE_X+469,467}}
  36. };
  37.  
  38. /* Each coordinate describes the y value of each line of the board. */
  39. #define BASE_Y  132
  40.  
  41. NXCoord horizontal[] = {
  42.   BASE_Y, BASE_Y+54, BASE_Y+106, BASE_Y+153,
  43.   BASE_Y+196, BASE_Y+237, BASE_Y+277, BASE_Y+312, BASE_Y+345
  44. };
  45.  
  46. id pieces3D;
  47.  
  48. void convert_point( NXPoint *p, int *r, int *c );
  49.  
  50. @implementation Board3D
  51.  
  52. + newFrame: (const NXRect *)f
  53. {
  54.   int r, c, i;
  55.   
  56.   self = [super newFrame: f];
  57.   [self allocateGState];
  58.   background = [NXImage newFromSection: "3d_board.tiff"];
  59.   [background setFlipped: NO];
  60.   pieces3D = [NXImage newFromSection: "3d_pieces.tiff"];
  61.   [pieces3D setFlipped: NO];
  62.   backBitmap = [Bitmap newSize: BACK_STORE_WIDTH: BACK_STORE_HEIGHT
  63.           type: NX_UNIQUEBITMAP];
  64.   [backBitmap setFlip: NO];
  65.   for( r = 0; r < 8; r++ )
  66.     for( c = 0; c < 8; c++ )
  67.       square[r][c] = [Square3D new];
  68.   [self setupPieces];
  69.   return self;
  70. }
  71.  
  72. - setBackgroundBitmap: sender
  73. {
  74.   background = sender;
  75.   [background setFlipped: NO];
  76. }
  77. - backgroundBitmap {return pieces3D;}
  78. - setupPieces
  79. {
  80.   [self layoutBoard: Stboard color:Stcolor];
  81. }
  82.  
  83. - layoutBoard: (short *)b color: (short *)c
  84. {
  85.   int sq, row, col;
  86.   
  87.   PSgsave();
  88.   PSrotate ( 10.0 );
  89.   for (sq = 0; sq < 64; sq++){
  90.     row = sq / 8;
  91.     col = sq % 8;
  92.     [self placePiece: b[sq] at: row: col color: c[sq]];
  93.   }
  94.   PSgrestore();
  95. }
  96.  
  97. squareOrigin( int r, int c, NXCoord *x, NXCoord *y )
  98. {
  99.   NXCoord dx,m,b;
  100.   
  101.   *y = horizontal[r];
  102.   dx = (vertical[c].a.x-vertical[c].b.x);
  103.   m = (vertical[c].a.y - vertical[c].b.y) / dx;
  104.   b = vertical[c].b.y - (m*vertical[c].b.x);
  105.   *x = dx ? (horizontal[r] - b)/m : vertical[c].a.x;
  106. }
  107.  
  108. squareBounds( int r, int c, NXPoint *p1, NXPoint *p2, NXPoint *p3, NXPoint *p4 )
  109. /*
  110.    (p2)----(p4)
  111.     |        |
  112.     |        |
  113.    (p1)----(p3)
  114. */
  115. {
  116.   NXCoord dx,m,b;
  117.   
  118.   dx = (vertical[c].a.x-vertical[c].b.x);
  119.   m = (vertical[c].a.y - vertical[c].b.y) / dx;
  120.   b = vertical[c].b.y - (m*vertical[c].b.x);
  121.   p1->y = floor( horizontal[r] );
  122.   p1->x = floor( dx ? (horizontal[r] - b)/m : vertical[c].a.x );
  123.  
  124.   p2->y = floor( horizontal[r+1] );
  125.   p2->x = floor( dx ? (horizontal[r+1] - b)/m : vertical[c].a.x );
  126.   
  127.   dx = (vertical[c+1].a.x-vertical[c+1].b.x);
  128.   m = (vertical[c+1].a.y - vertical[c+1].b.y) / dx;
  129.   b = vertical[c+1].b.y - (m*vertical[c+1].b.x);
  130.   p3->y = floor( horizontal[r] );
  131.   p3->x = floor( dx ? (horizontal[r] - b)/m : vertical[c+1].a.x );
  132.  
  133.   p4->y = floor( horizontal[r+1] );
  134.   p4->x = floor( dx ? (horizontal[r+1] - b)/m : vertical[c+1].a.x );
  135. }
  136.   
  137.  
  138. - slidePieceFrom: (int)r1 : (int)c1 to: (int)r2 : (int)c2
  139. {
  140.   NXPoint p, backP, centerP, endP;
  141.   NXRect backR;
  142.   int controlGState, type, color, increments, dr, dc, i;
  143.   NXRect newLocation, oldLocation;
  144.   NXCoord incX, incY;
  145.   
  146.   [self lockFocus];
  147.   type = [square[r1][c1] type];
  148.   color = [square[r1][c1] colorVal];
  149.   oldLocation = *[square[r1][c1] location];
  150.   if( !type )
  151.     return self;
  152.     
  153.   squareOrigin( r2, c2, &endP.x, &endP.y );
  154.   
  155.   /* Remove piece and then save background */ 
  156.   [square[r1][c1] setType: 0 color: 0];
  157.   [self drawSelf: 0 : 0];
  158.  
  159.   squareOrigin( r1, c1, &backP.x, &backP.y );
  160.   controlGState = [self gState];
  161.   [backBitmap lockFocus];
  162.   PSgsave();
  163.   PScomposite( backP.x, backP.y, BACK_STORE_WIDTH, BACK_STORE_HEIGHT,
  164.            controlGState, 
  165.            0.0, 0.0, NX_COPY);
  166.   PSgrestore();
  167.   [backBitmap unlockFocus];
  168.  
  169.   [square[r1][c1] setType: type color: color];
  170.   [square[r1][c1] drawInside: 0 inView: self];
  171.   [square[r1][c1] setMoving: YES];
  172.   PSflushgraphics();
  173.   NXPing();
  174.  
  175.   incX = endP.x - backP.x;
  176.   incY = endP.y - backP.y;
  177.   increments = (int) MAX( ABS(incX), ABS(incY) ) / 7;    // was 5 gcr
  178.   incX = incX / increments;
  179.   incY = incY / increments;
  180.   for( i = 0; i < increments; i++ ){
  181.     /* Restore old background */
  182.     [self lockFocus];
  183.     [backBitmap composite:NX_COPY toPoint: &backP];
  184.     [self unlockFocus];
  185.     
  186.     backP.x += incX;
  187.     backP.y += incY;
  188.     convert_point( &backP, &dr, &dc );
  189.  
  190.     /* Save new background */
  191.     [backBitmap lockFocus];
  192. //    PSgsave();
  193.     PScomposite( backP.x, backP.y,
  194.          BACK_STORE_WIDTH, BACK_STORE_HEIGHT,
  195.          controlGState, 
  196.          0.0, 0.0, NX_COPY);
  197. //    PSgrestore();
  198.     [backBitmap unlockFocus];
  199.     
  200.     /* Draw piece at new location. */
  201.     [square[r1][c1] setRow: dr];
  202.     newLocation.origin = backP;
  203.     newLocation.size.width = PIECE_WIDTH_3D;
  204.     newLocation.size.height = PIECE_HEIGHT_3D;
  205.     [square[r1][c1] setLocation: &newLocation];
  206.     [square[r1][c1] drawInside: 0 inView: self];
  207.  
  208.     PSflushgraphics();
  209.     NXPing();
  210.   }
  211.   
  212.   [square[r1][c1] setMoving: NO];
  213.  
  214.   [self unlockFocus];
  215. }
  216.  
  217.  
  218. - placePiece: (int)p at: (int)r : (int)c color: (int)col
  219. {
  220.   NXRect l;
  221.   NXCoord m,b,dx,x;
  222.  
  223.   [square[r][c] setType: p color: col];
  224.   [square[r][c] setRow: r];
  225.   l.origin.y = horizontal[r];
  226.   dx = (vertical[c].a.x-vertical[c].b.x);
  227.   m = (vertical[c].a.y - vertical[c].b.y) / dx;
  228.   b = vertical[c].b.y - (m*vertical[c].b.x);
  229.   x = dx ? (horizontal[r] - b)/m : vertical[c].a.x;
  230.   l.origin.x = x;
  231.  
  232.   dx = (vertical[c+1].a.x-vertical[c+1].b.x);
  233.   m = (vertical[c+1].a.y - vertical[c+1].b.y) / dx;
  234.   b = vertical[c+1].b.y - (m*vertical[c+1].b.x);
  235.   x = dx ? (horizontal[r] - b)/m : vertical[c+1].a.x;
  236.   l.size.width = x - l.origin.x;
  237.   l.size.height = 99999;
  238.   [square[r][c] setLocation: &l];
  239. }
  240.  
  241. - (int)typeAt: (int)r : (int)c
  242. {
  243.   return( (r>=0 && c>=0) ? [square[r][c] type] : 0 );
  244. }
  245.   
  246. - (int)colorAt: (int)r : (int)c
  247. {
  248.   return( (r>=0 && c>=0) ? [square[r][c] colorVal] : 0 );
  249. }
  250.   
  251. - drawRows: (int)r from: (int)c
  252. {
  253.   while( r >= 0 ){
  254.     if( [self typeAt: r : c] && ![square[r][c] moving] )
  255.       [square[r][c] drawInside: 0 inView: self];
  256.     r--;
  257.   }
  258. }
  259.     
  260. - unhighlightSquareAt: (int)r : (int) c
  261. {
  262.   NXPoint p1,p2,p3,p4,to;
  263.   NXRect backR;
  264.   
  265.   squareBounds( r, c, &p1, &p2, &p3, &p4 );
  266.   p1.x = p1.x - 3;
  267.   p1.y = p1.y - 3;
  268.   p2.x = p2.x - 3;
  269.   p2.y = p2.y + 3;
  270.   p3.x = p3.x + 3;
  271.   p3.y = p3.y - 3;
  272.   p4.x = p4.x + 3;
  273.   p4.y = p4.y + 3;
  274.   to.y = p1.y;
  275.   to.x = MIN(p1.x,p2.x);
  276.   backR.origin = to;
  277.   backR.size.width = MAX(p3.x,p4.x) - to.x;
  278.   backR.size.height = p2.y - p1.y;
  279.   
  280.   [self lockFocus];
  281.   
  282.   PSgsave();
  283.   PSsetlinewidth( 3.0 );
  284.   PSsetgray( 1.0 );
  285.   PSnewpath();
  286.   PSmoveto( p1.x, p1.y );
  287.   PSlineto( p2.x, p2.y );
  288.   PSlineto( p4.x, p4.y );
  289.   PSlineto( p3.x, p3.y );
  290.   PSlineto( p1.x, p1.y );
  291.   PSclosepath;
  292.   PSclip();
  293.   [background composite: NX_COPY fromRect: &backR toPoint: &to];
  294.   PSgrestore();
  295.   if( [self typeAt:r :c] || ( r > 0 && [self typeAt:r-1 :c]) )
  296.     [self drawRows: r from: c];
  297.   PSflushgraphics();
  298.   NXPing();
  299.   
  300.   [self unlockFocus];
  301. }
  302.  
  303. - highlightSquareAt: (int)r : (int) c
  304. {
  305.   struct timeval timeout;
  306.   NXPoint p1,p2,p3,p4;
  307.   short idx;
  308.   float color = 0.0;
  309.   
  310.   squareBounds( r, c, &p1, &p2, &p3, &p4 );
  311.   [self lockFocus];
  312.  
  313.   PSgsave();
  314.   PSsetlinewidth( 3.0 );
  315.   PSmoveto( p1.x, p1.y );
  316.   PSlineto( p2.x, p2.y );
  317.   PSlineto( p4.x, p4.y );
  318.   PSlineto( p3.x, p3.y );
  319.   PSlineto( p1.x, p1.y );
  320.   PSclosepath();
  321.   /* flash 2 times */
  322.   for ( idx=1; idx <= 3; idx++ ) {
  323.       color = 1.0 - color;
  324.       PSsetgray( color );
  325.       PSgsave(); 
  326.       PSstroke();
  327.       PSgrestore();
  328.       if( [self typeAt:r :c] || ( r > 0 && [self typeAt:r-1 :c]) )
  329.     [self drawRows: r from: c];
  330.       PSflushgraphics();
  331.       NXPing();
  332.       if( ![square[r][c] moving] ){ 
  333.     timeout.tv_sec = 0;
  334.     timeout.tv_usec = 15000;
  335.     select( 0, 0, 0, 0, &timeout );
  336.       }
  337.   }
  338.   PSgrestore();
  339.  /****
  340.   PSgsave();
  341.   PSsetlinewidth( 3.0 );
  342.   PSsetgray( 0.0 );
  343.   PSnewpath();
  344.   PSmoveto( p1.x, p1.y );
  345.   PSlineto( p2.x, p2.y );
  346.   PSlineto( p4.x, p4.y );
  347.   PSlineto( p3.x, p3.y );
  348.   PSlineto( p1.x, p1.y );
  349.   PSclosepath;
  350.   PSstroke();
  351.   PSgrestore();
  352.   if( [self typeAt:r :c] || ( r > 0 && [self typeAt:r-1 :c]) )
  353.     [self drawRows: r from: c];
  354.   PSflushgraphics();
  355.   NXPing();
  356.   if( ![square[r][c] moving] ){ 
  357.     timeout.tv_sec = 0;
  358.     timeout.tv_usec = 150000;
  359.     select( 0, 0, 0, 0, &timeout );
  360.   }
  361.  
  362.   PSgsave();
  363.   PSsetlinewidth( 3.0 );
  364.   PSsetgray( 1.0 );
  365.   PSnewpath();
  366.   PSmoveto( p1.x, p1.y );
  367.   PSlineto( p2.x, p2.y );
  368.   PSlineto( p4.x, p4.y );
  369.   PSlineto( p3.x, p3.y );
  370.   PSlineto( p1.x, p1.y );
  371.   PSclosepath;
  372.   PSstroke();
  373.   PSgrestore();
  374.   if( [self typeAt:r :c] || ( r > 0 && [self typeAt:r-1 :c]) )
  375.     [self drawRows: r from: c];
  376.   PSflushgraphics();
  377.   NXPing();
  378.   if( ![square[r][c] moving] ){ 
  379.     timeout.tv_sec = 0;
  380.     timeout.tv_usec = 150000;
  381.     select( 0, 0, 0, 0, &timeout );
  382.   }
  383.   ******/
  384.   [self unhighlightSquareAt: r : c];
  385.  
  386.   [self unlockFocus];
  387. }
  388.  
  389. - flashSquareAt: (int)r : (int) c
  390. {
  391.   NXPoint p1,p2,p3,p4;
  392.   
  393.   squareBounds( r, c, &p1, &p2, &p3, &p4 );
  394.   [self lockFocus];
  395.  
  396.   PSgsave();
  397.   PSsetlinewidth( 3.0 );
  398.   PSsetgray( 1.0 );
  399.   PSnewpath();
  400.   PSmoveto( p1.x, p1.y );
  401.   PSlineto( p2.x, p2.y );
  402.   PSlineto( p4.x, p4.y );
  403.   PSlineto( p3.x, p3.y );
  404.   PSlineto( p1.x, p1.y );
  405.   PSclosepath;
  406.   PSstroke();
  407.   PSgrestore();
  408.   if( [self typeAt:r :c] || ( r > 0 && [self typeAt:r-1 :c]) )
  409.     [self drawRows: r from: c];
  410.   [self unlockFocus];
  411. }
  412.  
  413.  
  414.  
  415. - printPSCode: sender
  416. {
  417.   id pi = [NXApp printInfo];
  418.   const NXRect *pr;
  419.   NXCoord lm, rm, tm, bm;
  420.   
  421.   pr = [pi paperRect];
  422.   lm = rm = (pr->size.width - frame.size.width) / 2.0;
  423.   tm = bm = (pr->size.height - frame.size.height) / 2.0;
  424.   [pi setMarginLeft: lm right: rm top: tm bottom: bm];
  425.   
  426.   [self lockFocus];
  427.   NXSizeBitmap( &bounds, &print_size, &print_pwide, &print_phigh,
  428.                 &print_bps, &print_ssp, &print_config, &print_mask );
  429.   print_image = (void *)malloc( print_size );
  430.   NXReadBitmap( &bounds, print_pwide, print_phigh, print_bps, print_ssp,
  431.            print_config, print_mask, print_image, 0, 0, 0, 0 );
  432.   [super printPSCode: self];
  433.   free( print_image );
  434.   [self unlockFocus];
  435.   return self;
  436. }
  437.  
  438. - drawSelf:(const NXRect *)f :(int)rectCount;
  439. {
  440.   int r, c;
  441.   NXRect cr;
  442.   NXPoint p;
  443.   
  444.   p.x = p.y = 0.0;
  445.   if( NXDrawingStatus == NX_DRAWING ){
  446.     PSgsave();
  447.     
  448.     [background composite: NX_COPY toPoint: &p];
  449.     for( r = 7; r >= 0; r-- ){
  450.       for( c = 7; c >= 0; c-- ){
  451.     [square[r][c] drawSelf: &cr inView: self];
  452.       }
  453.     }
  454.     PSgrestore();
  455.   }
  456.   else{
  457.     NXImageBitmap( &bounds, print_pwide, print_phigh, print_bps, print_ssp,
  458.                    print_config, print_mask, print_image, 0, 0, 0, 0 );
  459.   }
  460. }
  461.  
  462. - mouseDown: (NXEvent *)event
  463. {
  464.   NXPoint p, pickedP, backP, centerP;
  465.   NXHandler handler;
  466.   NXRect pieceRect, backR;
  467.   int r, c, r2, c2, mask, controlGState, t, col;
  468.   unsigned short mv;
  469.   NXRect newLocation, oldLocation;
  470.   NXCoord x, y;
  471.   int hi_r = -1, hi_c = -1;
  472.  
  473.   if ( [NXApp bothsides] ) {
  474.       NXBeep();
  475.       return self;
  476.   }
  477.  
  478.   if( [NXApp finished] ){
  479.     [NXApp finishedAlert];
  480.     handler.code = 0;
  481.     [window addToEventMask: NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK];
  482.     NX_DURING
  483.       while (event->type != NX_MOUSEUP){
  484.     event = [NXApp getNextEvent:NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK];
  485.       }
  486.     NX_HANDLER
  487.       handler = NXLocalHandler;
  488.     NX_ENDHANDLER
  489.     return self;
  490.   }
  491.   
  492.   pickedP = event->location;
  493.   [self convertPoint:&pickedP fromView:nil];
  494.   backP = pickedP;
  495.   
  496.   r = -1;
  497.   c = -1;
  498.   convert_point( &pickedP, &r, &c );
  499.   if( r == -1 || c == -1 )
  500.     return self;
  501.  
  502.   [self lockFocus];
  503.   t = [square[r][c] type];
  504.   col = [square[r][c] colorVal];
  505.   oldLocation = *[square[r][c] location];
  506.   if( t ){
  507.     [square[r][c] setType: 0 color: 0];
  508.     [self drawSelf: 0 : 0];
  509.  
  510.     [self flashSquareAt: r : c];
  511.     hi_r = r; hi_c = c;
  512.     
  513.     /* Save background */ 
  514.     squareOrigin( r, c, &x, &y );
  515.     backP.x = x;
  516.     backP.y = y;
  517.     controlGState = [self gState];
  518.     [backBitmap lockFocus];
  519.     PSgsave();
  520.     PScomposite( backP.x, backP.y, BACK_STORE_WIDTH, BACK_STORE_HEIGHT,
  521.          controlGState, 
  522.          0.0, 0.0, NX_COPY);
  523.     PSgrestore();
  524.     [backBitmap unlockFocus];
  525.  
  526.     [square[r][c] setType: t color: col];
  527.     [square[r][c] drawInside: 0 inView: self];
  528.     [square[r][c] setMoving: YES];
  529.     PSflushgraphics();
  530.     NXPing();
  531.     
  532.     pickedP.x = floor( pickedP.x - x );
  533.     pickedP.y = floor( pickedP.y - y );
  534.   }
  535.  
  536.   r2 = 0; c2 = 0;
  537.   handler.code = 0;
  538.   [window addToEventMask: NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK];
  539.   NX_DURING
  540.     while (event->type != NX_MOUSEUP){
  541.       event = [NXApp getNextEvent:NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK];
  542.       if( !t )
  543.         continue;
  544.     
  545.       p = event->location;
  546.       [self convertPoint:&p fromView:nil];
  547.  
  548.       /* Restore old background */
  549.       [self lockFocus];
  550.       [backBitmap composite:NX_COPY toPoint: &backP];
  551.       [self unlockFocus];
  552.       
  553.       backP.x = p.x - pickedP.x;
  554.       backP.y = p.y - pickedP.y;
  555.  
  556.       /* Un/highlight square */
  557.       centerP.y = backP.y + PIECE_HEIGHT_3D/4.0;
  558.       centerP.x = backP.x + PIECE_WIDTH_3D/2.0;
  559.       convert_point( ¢erP, &r2, &c2);
  560.       if( r2 != hi_r || c2 != hi_c ){
  561.         if( hi_r != -1 && hi_c != -1 )
  562.       [self unhighlightSquareAt: hi_r : hi_c];
  563.         hi_r = r2; hi_c = c2;
  564.     [self flashSquareAt: r2 : c2];
  565.       }
  566.  
  567.       /* Save new background */
  568.       [backBitmap lockFocus];
  569.       PSgsave();
  570.       PScomposite( backP.x, backP.y,
  571.            BACK_STORE_WIDTH, BACK_STORE_HEIGHT,
  572.            controlGState, 
  573.            0.0, 0.0, NX_COPY);
  574.       PSgrestore();
  575.       [backBitmap unlockFocus];
  576.       
  577.       /* Draw piece at new location. */
  578.       [square[r][c] setRow: r2];
  579.       newLocation.origin.x = p.x - pickedP.x;
  580.       newLocation.origin.y = p.y - pickedP.y;
  581.       newLocation.size.width = PIECE_WIDTH_3D;
  582.       newLocation.size.height = PIECE_HEIGHT_3D;
  583.       [square[r][c] setLocation: &newLocation];
  584.       [square[r][c] drawInside: 0 inView: self];
  585.  
  586.       PSflushgraphics();
  587.       NXPing();
  588.     }
  589.   NX_HANDLER
  590.     handler = NXLocalHandler;
  591.   NX_ENDHANDLER
  592.  
  593.   
  594.   if( t ){
  595.     [square[r][c] setMoving: NO];
  596.     if( r2 != r || c2 != c ){
  597.       if( ![NXApp makeMoveFrom: r : c to: r2 : c2] ){
  598.         [square[r][c] setLocation: &oldLocation];
  599.     [square[r][c] setType: t color: col];
  600.     [square[r][c] setRow: r];
  601.       }
  602.     }
  603.     else{
  604.       [square[r][c] setLocation: &oldLocation];
  605.       [square[r][c] setType: t color: col];
  606.       [square[r][c] setRow: r];
  607.     }
  608.     [self display];
  609.     PSflushgraphics();
  610.     NXPing();
  611.   }
  612.   [self unlockFocus];
  613.   
  614.   if (handler.code) {
  615.     NX_RAISE(handler.code, handler.data1, handler.data2);
  616.   }
  617. }
  618.  
  619.  
  620. NXCoord
  621. check_point( struct NXLine *l, NXPoint *p )
  622. {
  623.   NXCoord dx,dy,dx1,dy1;
  624.   
  625.   dx = l->a.x - l->b.x;
  626.   dy = l->a.y - l->b.y;
  627.   dx1 = p->x - l->a.x;
  628.   dy1 = p->y - l->a.y;
  629.   return( dx*dy1 - dy*dx1 );
  630. }
  631.  
  632. void
  633. convert_point( NXPoint *p, int *r, int *c )
  634. {
  635.   NXCoord dx,dy,dx1,dy1,m;
  636.   int i;
  637.   
  638.   for( i = 0; i < 8; i++ )
  639.     if( p->y >= horizontal[i] && p->y <= horizontal[i+1] ){
  640.       *r = i;
  641.       break;
  642.     }
  643.       
  644.   for( i = 0; i < 8; i++ ){
  645.     NXCoord m1,m2;
  646.     
  647.     m1 = check_point( &vertical[i], p );
  648.     m2 = check_point( &vertical[i+1], p );
  649.     if( m1 > 0 && m2 < 0 ){
  650.       *c = i;
  651.       break;
  652.     }
  653.   }
  654. }  
  655.  
  656.  
  657. @end
  658.